﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace ArgusLib.Controls
{
	public abstract class FilesystemEntryTextBox : TextBox
	{
		List<char> invalidChars;
		string validatedText;

		public FileSystemInfo FileSystemInfo { get; private set; }

		public FilesystemEntryTextBox()
			: base()
		{
			this.invalidChars = new List<char>(this.GetInvalidChars());
			this.validatedText = string.Empty;
			this.FileSystemInfo = this.GetFileSystemInfo(string.Empty);
		}

		protected abstract IEnumerable<char> GetInvalidChars();
		protected abstract FileSystemInfo GetFileSystemInfo(string text);

		protected override void OnKeyPress(System.Windows.Forms.KeyPressEventArgs e)
		{
			if (char.IsControl(e.KeyChar) == false && this.invalidChars.Contains(e.KeyChar) == true)
				e.Handled = true;
			base.OnKeyPress(e);
		}

		protected override void OnTextChanged(EventArgs e)
		{
			if (this.Validate() == true)
				base.OnTextChanged(e);
		}

		private bool Validate()
		{
			if (string.IsNullOrEmpty(this.Text) == true)
				return true;

			string text = this.Text;
			FileSystemInfo fsi = this.GetFileSystemInfo(text);
			if (fsi == null)
			{
				text = text.RemoveChars(this.invalidChars);
				fsi = this.GetFileSystemInfo(text);
			}

			if (fsi == null)
			{
				this.Text = this.validatedText;
				return false;
			}
			else
			{
				this.validatedText = this.Text;
				this.FileSystemInfo = fsi;
				return true;
			}
		}

		protected override void OnLostFocus(EventArgs e)
		{
			if (this.FileSystemInfo != null)
				this.Text = this.FileSystemInfo.FullName;
			base.OnLostFocus(e);
		}

		protected override void OnKeyDown(System.Windows.Forms.KeyEventArgs e)
		{
			if (e.KeyCode == System.Windows.Forms.Keys.Enter && this.FileSystemInfo != null)
				this.Text = this.FileSystemInfo.FullName;
			base.OnKeyDown(e);
		}
	}

	public class FilenameTextBox : FilesystemEntryTextBox
	{
		public FilenameTextBox()
			: base() { }

		public FileInfo FileInfo { get { return this.FileSystemInfo as FileInfo; } }

		protected override IEnumerable<char> GetInvalidChars()
		{
			return Path.GetInvalidFileNameChars();
		}

		protected override FileSystemInfo GetFileSystemInfo(string text)
		{
			try { return new FileInfo(text); }
			catch { return null; }
		}
	}

	public class FolderpathTextBox : FilesystemEntryTextBox
	{
		public FolderpathTextBox()
			: base() { }

		public DirectoryInfo DirectoryInfo { get { return this.FileSystemInfo as DirectoryInfo; } }

		protected override IEnumerable<char> GetInvalidChars()
		{
			return Path.GetInvalidPathChars();
		}

		protected override FileSystemInfo GetFileSystemInfo(string text)
		{
			try { return new DirectoryInfo(text); }
			catch { return null; }
		}
	}
}
